package game;

import java.util.*;

/**
 * Modification permet de modifier un plateau de jeu pour passer d'une etape a
 * une autre
 */
public class Modification {

	/**
	 * simu modifie un plateau, notamment sa liste pour simuler l'evolution des
	 * cellules lors d'une etape
	 * 
	 * @param plateau
	 *            : plateau de jeu
	 * @return la liste de cellules du plateau modifiee en fonction des
	 *         naissances et des deces des cellules
	 */
	public static ArrayList<Cellule> simu(Plateau plateau) {
		ArrayList<Cellule> liste = plateau.getJeu();
		initialisation(liste);
		for (int i = 0; i < liste.size(); i++) {
			Cellule c = liste.get(i);
			if (c.traite == false) {
				for (int x = (c.posX) - 1; x <= (c.posX) + 1; x++) {
					for (int y = (c.posY) - 1; y <= (c.posY) + 1; y++) {
						Cellule cbis = new Cellule(x, y);
						if (!liste.contains(cbis)) {
							cbis.etat = 1;
							traitermort(cbis, plateau);
						}
					}
				}
			}
			traitervivant(c, plateau);
		}
		fintraiter(liste);
		Collections.sort(liste, Collections.reverseOrder());
		return liste;
	}

	/**
	 * traitermort cree les cellules mortes qui doivent naitre
	 * 
	 * @param c
	 *            : cellule morte qui va etre traitee
	 * @param p
	 *            : plateau de jeu contenant la liste des cellules vivantes et
	 *            les regles de vie, de mort et de frontieres
	 * @return le booleen vrai une fois la cellule traitee (cree ou non) et
	 *         faux si la cellule est en dehors des frontieres
	 */
	public static boolean traitermort(Cellule c, Plateau p) {
		ArrayList<Integer> naitre = p.getMort();
		int voisin = nbVoisin(p.getJeu(), c);
		for (int i = 0; i < naitre.size(); i++) {
			if (voisin == naitre.get(i)) {
				c.etat = 0;
				c.traite = true;
				p.getJeu().add(c);
				return true;
			}
		}
		c.traite = true;
		return true;
	}

	/**
	 * traitervivant traite les cellules vivantes en determinant si elle doivent
	 * mourir ou rester en vie
	 * 
	 * @param c
	 *            : cellules vivante trait�e
	 * @param p
	 *            : plateau de jeu contenant la liste des cellules vivantes et
	 *            les regles de vie, de mort et de frontieres
	 * @return le booleen vrai une fois la cellule traitee
	 */
	public static boolean traitervivant(Cellule c, Plateau p) {
		ArrayList<Integer> en_vie = p.getVie();
		int voisin = nbVoisin(p.getJeu(), c);
		for (int i = 0; i < en_vie.size(); i++) {
			if (voisin == en_vie.get(i)) {
				c.traite = true;
				return true;

			}
		}
		c.traite = true;
		c.etat = 1;
		return true;
	}

	/**
	 * fintraiter supprime de la liste toutes les cellules passees a l'etat de
	 * mortes
	 * 
	 * @param liste
	 *            : liste de cellules
	 */
	public static void fintraiter(ArrayList<Cellule> liste) {
		int cpt;
		do {
			cpt = 0;
			for (int i = 0; i < liste.size(); i++) {
				if (liste.get(i).etat == 1) {
					liste.remove(i);
					cpt++;
				}
			}
		} while (cpt != 0);
	}

	/**
	 * initialisation remet la liste a l'etat initiale, c'est-a-dire remet
	 * toutes les cellules a l'etat vivante et non traitees
	 * 
	 * @param liste
	 *            : liste de cellule
	 */
	public static void initialisation(ArrayList<Cellule> liste) {
		for (int i = 0; i < liste.size(); i++) {
			liste.get(i).traite = false;
			liste.get(i).etat = 2;
		}
	}

	/**
	 * nbVoisin compte le nombre de voisin d'une cellule donnee dans une liste
	 * de cellules
	 * 
	 * @param l
	 *            : liste de cellules
	 * @param c
	 *            : cellule dont on compte le nombre de voisin
	 * @return le nombre de voisin de la cellule
	 */
	public static int nbVoisin(ArrayList<Cellule> l, Cellule c) {
		int cpt = 0;
		int taille = l.size();
		for (int y = c.posY - 1; y <= c.posY + 1; y++) {
			for (int x = c.posX - 1; x <= c.posX + 1; x++) {
				for (int i = 0; i < taille; i++) {
					if ((l.get(i).posX == x) && (l.get(i).posY == y)
							&& (l.get(i).etat != 0)) {
						cpt++;
					}
				}
			}
		}
		if ((l.contains(c)) && (c.etat != 0)) {
			cpt--;
		}
		return cpt;
	}
}